package priv.conceit.study.leetcode.medium;

import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.CyclicBarrier;

/**
 * 编号：1115
 * 交替打印FooBar
 *
 * <a href="https://leetcode-cn.com/problems/print-foobar-alternately/">
 * @return:
 * @author: conceit
 * @date: 2019/11/1 15:00
 */
public class PrintFoobarAlternately4 {
	private int n;
	CyclicBarrier barrier;
	CountDownLatch countDownLatch;

	/**
	 * 实现线程交替打印
	 * 使用循环格栅 控制每次循环统一执行
	 * {@link CyclicBarrier#await()}
	 * 线程进行等待，直到设定数目的线程都等待完成，在进行下一步操作，但是无法保持线程间的执行顺序
	 *
	 * 使用闭锁 控制每次循环执行顺序
	 * {@link CountDownLatch#countDown()}计数器-1
	 * {@link CountDownLatch#await()}线程进行等待 直到计数器=0
	 *
	 *
	 * @param args
	 * @throws InterruptedException
	 */
	public static void main(String[] args) throws InterruptedException {
		PrintFoobarAlternately4 foobar4 = new PrintFoobarAlternately4(10);
		new Thread(()->{
			try {
				foobar4.foo(()->System.out.println("foo"));
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
			}
		}).start();

		new Thread(()->{
			try {
				foobar4.bar(()->System.out.println("bar"));
			} catch (InterruptedException e) {
				e.printStackTrace();
			} catch (BrokenBarrierException e) {
				e.printStackTrace();
			}
		}).start();
	}

	public PrintFoobarAlternately4(int n) {
		this.n = n;
		barrier = new CyclicBarrier(2);
		countDownLatch=new CountDownLatch(1);
	}

	public void foo(Runnable printFoo) throws InterruptedException, BrokenBarrierException {
		for(int i=0;i<n;i++){
			printFoo.run();
			countDownLatch.countDown();
			barrier.await();
		}

	}

	public void bar(Runnable printBar) throws BrokenBarrierException, InterruptedException {
		for(int i=0;i<n;i++){
			countDownLatch.await();
			printBar.run();
			countDownLatch=new CountDownLatch(1);
			barrier.await();
		}
	}
}



